import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class GeneradorDeCasos {
	
	public static void main(String[] args) {	
		FileParser fp = new FileParser(".\\resources\\GrafoCompletoAleatorio10.txt");
		Grafo g1 = Tp3_Constructivo.parsearInstancia(fp);
		escribirMatrizAdyacencia(g1, "GrafoCompletoAleatorio10");
		
//		Set<Grafo> grafos= new HashSet<Grafo>();
//		for (int i=1;i<100;i++){
////			System.out.println(i + " -------------- ");
//			for (int j = 1 ; j <= 3; j++){
//				//linea para crear casos estrella---------------------
////				Grafo g = grafoCompletoKmasNmasEstrella(10,i,8,40);
//
//				//linea para crear casos Aleatorios---------------------
////				Grafo g = grafoCompletoKmasN(10,i,8);
////				Grafo g = grafoCompletoK(100,i);
//				Grafo g = grafosCompletosKmasNmasEstrella(10,15,i,8,40);
//
//				grafos.add(g);
//				//		Grafo g = grafoCompletoKmasN(30, 1000, 9);
//				//Grafo g = grafoParasito(17 , 20 , 80 , 7);
//				//escribirGrafo(g, "test");
////				Tp3_Constructivo.algoritmo("test.in", "mike.out", "mike.time");
////				Tp3_Ej1_Main.algoritmo("test.in", "mike.out", "mike.time");
//			}
//		}
//		//creoCaso(grafos, "100casos_ConDosCliquesyEstrella40");
		//escribirMatrizAdyacencia(g,"test");
		//System.out.println("-------------- " + i);
		//}
	}

	private static Grafo grafosCompletosKmasNmasEstrella(int p, int k, int n, int carga,int estrella){
		Grafo g = new Grafo(p+k+n+estrella);
		int nodoDePrimeraClique = 0;
		int nodoDeSegundaClique = 0;
		// GENERO GRAFO COMPLETO
		for (int i = 1; i < k; i++) {
			for (int j = i+1; j <= k; j++) {
					g.agregaEje(i, j);
					System.out.println(i + " - " + j);
			}
		nodoDePrimeraClique = i;	
		}

		// GENERO GRAFO COMPLETO PARASITO
		for (int i = k+1; i < k+p; i++) {
			for (int j = i+1; j <= k+p; j++) {
				g.agregaEje(i, j);
				System.out.println(i + " - " + j);
			}
			nodoDeSegundaClique = i;	
		}

		g.agregaEje(nodoDePrimeraClique, nodoDeSegundaClique);
		System.out.println(nodoDePrimeraClique + " - " + nodoDeSegundaClique);
		
		
		
		int nodosProcesados = k+p+1;
		
		for (int i = k+p+1; i <= k+p+n; i++) {
			for (int j = 1; j <= nodosProcesados; j++) {
				if (i != j) {
					int prob = (int) (Math.floor(Math.random()*10)+carga);
					if(prob > 10) {
						g.agregaEje(i, j);
						System.out.println(i + " - " + j);
					}
				}
			}
			nodosProcesados++;
		}
		g.agregaEje(1, nodosProcesados);
		g.agregaEje(nodosProcesados, nodosProcesados+1);
		
		for (int i = nodosProcesados+1; i <= k+p+n+estrella; i++) {
			if (i!=nodosProcesados+1){
				g.agregaEje(nodosProcesados+1, i);
				System.out.println(nodosProcesados+1 + " - " + i);
			}
			//nodosProcesados++;
		}
		
		return g;	
	} 

	
	
	private static Grafo grafoCompletoKmasNmasEstrella(int k, int n, int carga,int estrella){
		Grafo g = new Grafo(k+n+estrella);
		
		// GENERO GRAFO COMPLETO
		for (int i = 1; i < k; i++) {
			for (int j = i+1; j <= k; j++) {
					g.agregaEje(i, j);
					//System.out.println(i + " - " + j);
			}
		}
		
		int nodosProcesados = k+1;
		
		for (int i = k+1; i <= k+n; i++) {
			for (int j = 1; j <= nodosProcesados; j++) {
				if (i != j) {
					int prob = (int) (Math.floor(Math.random()*10)+carga);
					if(prob > 10) {
						g.agregaEje(i, j);
						//System.out.println(i + " - " + j);
					}
				}
			}
			nodosProcesados++;
		}
		g.agregaEje(1, nodosProcesados);
		g.agregaEje(nodosProcesados, nodosProcesados+1);
		
		for (int i = nodosProcesados+1; i <= k+n+estrella; i++) {
			if (i!=nodosProcesados+1){
				g.agregaEje(nodosProcesados+1, i);
			}
			//nodosProcesados++;
		}
		
		return g;	
	} 

	
	private static Grafo grafoCompletoK(int k, int n) {
		Grafo g = new Grafo(k+n);
		
		// GENERO GRAFO COMPLETO
		for (int i = 1; i < k+n; i++) {
			for (int j = i+1; j <= k+n; j++) {
					g.agregaEje(i, j);
//					System.out.println(i + " - " + j);
			}
		}		
		
		return g;
	}

	
	private static Grafo grafoCompletoKmasN(int k, int n, int carga) {
		Grafo g = new Grafo(k+n);
		
		// GENERO GRAFO COMPLETO
		for (int i = 1; i < k; i++) {
			for (int j = i+1; j <= k; j++) {
					g.agregaEje(i, j);
//					System.out.println(i + " - " + j);
			}
		}
		
		int nodosProcesados = k+1;
		
		for (int i = k+1; i <= k+n; i++) {
			for (int j = 1; j <=nodosProcesados; j++) {
				if (i != j) {
					int prob = (int) (Math.floor(Math.random()*10)+carga);
					if(prob > 10) {
						g.agregaEje(i, j);
//						System.out.println(i + " - " + j);
					}
				}
			}
			nodosProcesados++;
		}
		
		return g;
	}
	
	private static Grafo grafoParasito(int p, int k, int n, int carga) {
		Grafo g = new Grafo(p+k+n);
		
		// GENERO GRAFO COMPLETO
		for (int i = 1; i < k; i++) {
			for (int j = i+1; j <= k; j++) {
				g.agregaEje(i, j);
				//System.out.println(i + " - " + j);
			}
		}
		
		// GENERO GRAFO COMPLETO PARASITO
		for (int i = k+1; i < k+p; i++) {
			for (int j = i+1; j <= k+p; j++) {
				g.agregaEje(i, j);
				//System.out.println(i + " - " + j);
			}
		}
		
		int nodosProcesados = k+p+1;
		
		for (int i = k+p+1; i <= k+p+n; i++) {
			for (int j = 1; j <=nodosProcesados; j++) {
				if (i != j) {
					int prob = (int) (Math.floor(Math.random()*10)+carga);
					if(prob > 10) {
						g.agregaEje(i, j);
						//System.out.println(i + " - " + j);
					}
				}
			}
			nodosProcesados++;
		}
		
		return g;
	}
	
	private static void creoCaso(Set<Grafo> grafos, String nombreArchivo) {
		FileWriter f = new FileWriter(nombreArchivo+".in");
		Iterator<Grafo> it = grafos.iterator();
		while (it.hasNext()) {
			escribirGrafo(it.next(), f);
		}
		f.writeLine("-1");
		
		f.closeFile();
	}
	private static void escribirGrafo(Grafo g, FileWriter f) {
		
		f.writeLine(Integer.toString(g.getCantVertices()));
		
		for (int i = 1; i <= g.getCantVertices(); i++) {
			StringBuffer sb = new StringBuffer();
			Set<Integer> vecinos = g.obtengoVecinos(i);
			for (Integer v : vecinos) {
				sb.append(" "+v);
			}
			f.writeLine( vecinos.size() + sb.toString() );	
		}
	}

	private static void escribirMatrizAdyacencia(Grafo g, String nombreArchivo) {
		FileWriter f = new FileWriter(nombreArchivo+".in");
		
		int[][] matAdy = g.getMatAdy();
		
		for (int i = 0; i < g.getCantVertices(); i++) {
			StringBuffer sb = new StringBuffer();
			for (int j = 0; j < g.getCantVertices(); j++) {
				if (matAdy[j][i]==1)
					sb.append("1	");
				else
					sb.append("#	");
			}
			sb.append(";");
			f.writeLine(sb.toString() );	
		}
		
		f.closeFile();
	}
	
	private static boolean esConexo(Grafo g) {
		int cantNodosRecorridos = bfs(g);
		int cantNodos = g.getCantVertices();
		
		return (cantNodos == cantNodosRecorridos);
	}
	
	private static int bfs(Grafo g) {
		int cantVisitados = 0;
		/*
		int listaVisitadosConBfs[] = new int[g.getCantVertices()];
		Cola laCola = new Cola(g.getCantVertices());
				
		// Comenzamos en el primer vertice.
		listaVisitadosConBfs[0] = 1;
		laCola.push(0);
		cantVisitados++;
		
		while(!laCola.vacio()) {
			// Tomamos un vertice no visitado adyacente al primero de la cola.
			int v = getVerticesNoVisitados(p, laCola.peek(), listaVisitadosConBfs);
			
			if(v == -1) { // Si no hay tal vertice.
				laCola.pop(); // Lo desencolamos.
			} else {
				if (v == p.getCantHabitaciones()-1) {
					meEscape = true;
				} else {
					listaVisitadosConBfs[v] = 1; // Lo marcamos como visitado.
					
					if (p.getListaHabitacion()[v].isEsPuerta()) { // Si es puerta.
						if (llaves[v] == 1){ // Si tengo la llave.
							laCola.push(v);
						} else { // Si no tengo la llave.
							puertas[v] = 1; // Lo agrego al arreglo de las puertas.
						}
					} else { //Si no es puerta
						if (p.getListaHabitacion()[v].getLlave() != 0) { // Si es llave.
							if (llaves[p.getListaHabitacion()[v].getLlave()-1] == 1) { // Si ya la tengo.
								laCola.push(v);
							} else { // Si no la tengo.
								if (puertas[p.getListaHabitacion()[v].getLlave()- 1] == 1) { // Si tengo la puerta en el arreglo.
									llaves[p.getListaHabitacion()[v].getLlave()-1] = 1;
									laCola.push(v);
									laCola.push(p.getListaHabitacion()[v].getLlave()-1);
								} else { // Si no tengo la puerta en el arreglo. 
									llaves[p.getListaHabitacion()[v].getLlave()-1] = 1;
									laCola.push(v);
								}
							}
						} else { // Si no es llave.
							laCola.push(v);
						}
					}
				}
			}
		}
		*/
		return cantVisitados;
	}
	
	private static int getVerticesNoVisitados(Grafo g, int v, int[] listaVisitadosConBfs) {
		for(int j=0; j<g.getCantVertices(); j++) {
			if(g.estaRelacionado(v, j) && listaVisitadosConBfs[j]==0)
				return j;
		}
		
		return -1;
	}

}
